#ifndef PCPUPDATEPTL_H
#define PCPUPDATEPTL_H

#include <mutex>
#include <QByteArray>

#define PCPHEAD_LEN (8)

#define PCPHEAD_1 (0xFF)
#define PCPHEAD_2 (0xFE)

//#define PCPPACKETLEN (256)
#define PCPSENDBUFLEN (1024 + 32)
#define PCPRECVBUFLEN (64)

enum
{
    PCP_RET_SUCCESS = 0,
    PCP_DEV_USING,
    PCP_SIGNAL_WEAK,
    PCP_LATEST_VERSION,
    PCP_LOW_BATTERY,
    PCP_LOW_FLASH,
    PCP_DOWN_OVERTIME,
    PCP_PACKET_CRCFAIL,
    PCP_PACKET_ERRTYPE,
    PCP_LOW_MEMORY,
    PCP_UPDATE_FAILED,

    //0x0B ~ 0x7E 预留错误码
    PCP_INNER_ERR = 0x7F,
    PCP_UPDATE_INVALID,     //升级任务不存在
    PCP_FRAGMENT_INVALID,   //指定数据分片不存在
};

enum
{
    //0-18 平台预留消息码
    PCP_MSG_QUERY = 19,    //平台查询设备版本

    //平台新版本通知,新版本附带固件分片总数和校验码
    //设备回应允许升级,不允许升级原因
    PCP_MSG_NEWVER,

    PCP_MSG_PACKET_QEQUEST,//设备请求升级固件分片包
    PCP_MSG_PACKET_STATE,  //设备上报固件包完成后的下载状态
    PCP_MSG_UPDATE,        //平台下发执行升级
    PCP_MSG_UPDATE_RET,    //设备上报升级结果
    //25-127 平台预留消息码

    PCP_MSG_UPDATE_STOP = 129   //退出升级
};

enum
{
    UPDATE_RET_NONE = 0,
    UPDATE_RET_READY,
    UPDATE_RET_START,
    UPDATE_RET_STOP,
    UPDATE_RET_PACKET,
    UPDATE_RET_SUCESSED,  
    UPDATE_RET_REJECT,
    UPDATE_RET_FAILED,
    UPDATE_RET_CHECKERR
};

class PCPUpdatePtl
{
public:
    PCPUpdatePtl();

    uint16_t pcp_crc_16(uint8_t *data, uint32_t len);
    bool pcp_crc_check(uint8_t *data, uint16_t len);

    uint32_t reentrent_crc_32(uint8_t *, int32_t);

    static PCPUpdatePtl* Instance();

    bool pcp_new_version(const QByteArray&, QString &, quint16, bool);
    uint8_t pcp_parse_business(const QByteArray&, QString &, uint16_t &);

    void pcp_update_stop();

    bool pcp_is_update();
    void pcp_send_frame(uint8_t, uint16_t);

private:
    void pcp_send_newversion();

private:
    quint8 fireSendBuf[PCPSENDBUFLEN];
    quint8 fireRecvBuf[PCPRECVBUFLEN + 8];
    int fireRecvLen = 0;

    bool   m_UpdateCrc32 = false;
    qint32 mFirewareLen = 0;
    qint32 mFirewaretSndLen = 0;
    qint32 mFirewareCrc = 0;
    quint16 mPacketLen = 0;

    quint16 mPacketSegment = 256;

    bool m_IsUpdate = false;

    QByteArray mFireware;

    std::mutex m_Mutex;
};

#endif // PCPUPDATEPTL_H
